<?php

namespace App\Models;

use Carbon\Carbon;
use App\Models\Traits\OrderTrait;
use App\Models\Traits\HasScopeInquire;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Facades\Log;

/**
 * App\Models\Order
 *
 * @property int $id
 * @property int $user_id
 * @property int $gold_record_id
 * @property string $number number of this order
 * @property string $total_amount
 * @property string $total_profit
 * @property string|null $province
 * @property string|null $city
 * @property string|null $district
 * @property array|null $address json field: includes address,zip,contats
 * @property \Illuminate\Support\Carbon|null $paid_at
 * @property string|null $paid_method
 * @property string|null $paid_number
 * @property string $delivery_status
 * @property array|null $delivery_data data about delivery
 * @property \Illuminate\Support\Carbon|null $closed_at
 * @property \Illuminate\Support\Carbon|null $cancelled_at
 * @property \Illuminate\Support\Carbon|null $received_at
 * @property array|null $adapay_data adapay pay_info
 * @property array|null $extra_data extra data
 * @property bool $has_refund if this order items has any refund
 * @property bool $has_commented
 * @property \Illuminate\Support\Carbon|null $deleted_at
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property-read mixed $contact_address
 * @property-read mixed $contact_name
 * @property-read mixed $contact_phone
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\OrderItem[] $items
 * @property-read int|null $items_count
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\OrderRefund[] $refunds
 * @property-read int|null $refunds_count
 * @property-read \App\Models\User|null $user
 * @method static Builder|Order aftersales()
 * @method static Builder|Order cancelled()
 * @method static Builder|Order closed()
 * @method static Builder|Order delivered()
 * @method static \Database\Factories\OrderFactory factory(...$parameters)
 * @method static Builder|Order newModelQuery()
 * @method static Builder|Order newQuery()
 * @method static \Illuminate\Database\Query\Builder|Order onlyTrashed()
 * @method static Builder|Order paid()
 * @method static Builder|Order query()
 * @method static Builder|Order received()
 * @method static Builder|Order refunded()
 * @method static Builder|Order uncancelled()
 * @method static Builder|Order unclosed()
 * @method static Builder|Order uncommented()
 * @method static Builder|Order undelivered()
 * @method static Builder|Order unpaid()
 * @method static Builder|Order unrefunded()
 * @method static Builder|Order whereAdapayData($value)
 * @method static Builder|Order whereAddress($value)
 * @method static Builder|Order whereCancelledAt($value)
 * @method static Builder|Order whereCity($value)
 * @method static Builder|Order whereClosedAt($value)
 * @method static Builder|Order whereCreatedAt($value)
 * @method static Builder|Order whereDeletedAt($value)
 * @method static Builder|Order whereDeliveryData($value)
 * @method static Builder|Order whereDeliveryStatus($value)
 * @method static Builder|Order whereDistrict($value)
 * @method static Builder|Order whereExtraData($value)
 * @method static Builder|Order whereGoldRecordId($value)
 * @method static Builder|Order whereHasCommented($value)
 * @method static Builder|Order whereHasRefund($value)
 * @method static Builder|Order whereId($value)
 * @method static Builder|Order whereNumber($value)
 * @method static Builder|Order wherePaidAt($value)
 * @method static Builder|Order wherePaidMethod($value)
 * @method static Builder|Order wherePaidNumber($value)
 * @method static Builder|Order whereProvince($value)
 * @method static Builder|Order whereReceivedAt($value)
 * @method static Builder|Order whereTotalAmount($value)
 * @method static Builder|Order whereTotalProfit($value)
 * @method static Builder|Order whereUpdatedAt($value)
 * @method static Builder|Order whereUserId($value)
 * @method static \Illuminate\Database\Query\Builder|Order withTrashed()
 * @method static \Illuminate\Database\Query\Builder|Order withoutTrashed()
 * @mixin \Eloquent
 * @method static Builder|Order inquire($condition = null)
 * @property bool $is_gold_bean
 * @property bool $is_gold_coin
 * @method static Builder|Order whereIsGoldBean($value)
 * @method static Builder|Order whereIsGoldCoin($value)
 * @property int $gold_waste_id
 * @property-read \App\Models\GoldWaste|null $goldWaste
 * @method static Builder|Order whereGoldWasteId($value)
 */
class Order extends Model
{
    use HasFactory, SoftDeletes, OrderTrait, HasScopeInquire;

	protected $guarded = ['id'];

	protected $casts = [
		'has_refund' => 'boolean',
		'has_commented' => 'boolean',
		'is_gold_bean' => 'boolean',
		'is_gold_coin' => 'boolean',
		'address' => 'json',
		'delivery_data' => 'json',
		'adapay_data' => 'json',
		'extra_data' => 'json',
	];

	protected $dates = [
		'paid_at',
		'closed_at',
		'cancelled_at',
		'received_at'
	];

	static array $noAreas = [
		'150000' => '内蒙古自治区',
		'540000' => '西藏自治区',
		'620000' => '甘肃省',
		'630000' => '青海省',
		'640000' => '宁夏回族自治区',
		'650000' => '新疆维吾尔自治区',
	];

	static array $deliveryStatus = [
		'pending' => '待发货',
		'delivered' => '已发货',
		'received' => '已收货',
	];

	static array $inquireConditions = [
		'unpaid' => '待付款',
		'undelivered' => '待发货',
		'delivered' => '待收货',
		'uncommented' => '待评价',
		'aftersales' => '售后',
	];

	static array $refundStatus = [
		'pending'       => '待申请',
		'applied'       => '已申请',
		'refused'       => '拒绝售后',
		'confirmed'     => '审核通过',
		'processing'    => '正在退款',
		'succeeded'     => '退款成功',
		'failed'        => '退款失败',
	];

	public function scopeUnclosed(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at');
	}

	public function scopeClosed(Builder $builder): Builder
	{
		return $builder->whereNotNull('closed_at');
	}

	public function scopeUnpaid(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')->whereNull('paid_at');
	}

	public function scopePaid(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')->whereNotNull('paid_at');
	}

	public function scopeUncancelled(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')->whereNotNull('paid_at')->whereNull('cancelled_at');
	}

	public function scopeCancelled(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')->whereNotNull('paid_at')->whereNotNull('cancelled_at');
	}

	public function scopeUnrefunded(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')->whereNotNull('paid_at')
			->whereNull('cancelled_at')->where('has_refund', false);
	}

	public function scopeRefunded(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')->whereNotNull('paid_at')
			->whereNull('cancelled_at')->where('has_refund', true);
	}

	public function scopeUndelivered(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')->whereNotNull('paid_at')
			->whereNull('cancelled_at')->where('has_refund', false)->where('delivery_status', 'pending');
	}

	public function scopeDelivered(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')->whereNotNull('paid_at')
			->whereNull('cancelled_at')->where('has_refund', false)->where('delivery_status', 'delivered');
	}

	public function scopeReceived(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')->whereNotNull('paid_at')
			->whereNull('cancelled_at')->where('delivery_status', 'received');
	}

	public function scopeUncommented(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')->whereNotNull('paid_at')->whereNull('cancelled_at')
			->where('delivery_status', 'received')->where('has_commented', false)->where('has_refund', false);
	}

	public function scopeAftersales(Builder $builder): Builder
	{
		return $builder->whereNull('closed_at')
			->whereNotNull('paid_at')
			->whereNull('cancelled_at')
			->where('has_commented', false)
			->where('has_refund', false)
			->whereDate('created_at', '>', Carbon::now()->addDays(-15)->toDateString());
	}

	public function getContactNameAttribute()
	{
		return $this->address['contact_name'];
	}

	public function getContactPhoneAttribute()
	{
		return $this->address['contact_phone'];
	}

	public function getContactAddressAttribute()
	{
		return $this->address['address'];
	}

	public function isPaid(): bool
	{
		return (bool)$this->paid_at;
	}

	public function isClosed(): bool
	{
		return (bool)$this->closed_at;
	}

	public function isCancelled(): bool
	{
		return (bool)$this->cancelled_at;
	}

	public function isGoldBeanOrder(): bool
	{
		if ($this->is_gold_bean) {
			return true;
		}
		return $this->items()->first()->product->is_gold_bean;
	}

	public function isGoldStormOrder(): bool
	{
		if ($this->is_gold_coin) {
			return true;
		}
		return $this->items()->first()->product->is_gold_storm;
	}

	public function isProductReturnable(): bool
	{
		return $this->items()->first()->product->is_returnable;
	}

	public function deliveryCompany()
	{
		return isset($this->delivery_data['delivery_company']) ? $this->delivery_data['delivery_company'] : '';
	}

	public function deliveryNumber()
	{
		return isset($this->delivery_data['delivery_number']) ? $this->delivery_data['delivery_number'] : '';
	}

	public function deliveryTime()
	{
		$time = isset($this->delivery_data['delivery_time']) ? $this->delivery_data['delivery_time'] : '';
		return empty($time) ? null : time_to_carbon($time);
	}

	public function user(): BelongsTo
	{
		return $this->belongsTo(User::class);
	}

	public function items(): HasMany
	{
		return $this->hasMany(OrderItem::class, 'order_id', 'id');
	}

	public function refunds(): HasMany
	{
		return $this->hasMany(OrderRefund::class);
	}

    public function goldWaste(): BelongsTo
    {
        return $this->belongsTo(GoldWaste::class);
    }

    public function seckillProduct(): BelongsTo
    {
        return $this->belongsTo(SeckillProduct::class);
    }
}
